home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Mac / Demo / textedit / ped.py
Encoding:
Text File  |  2000-06-23  |  7.9 KB  |  346 lines

  1. # A minimal text editor.
  2. #
  3. # To be done:
  4. # - Update viewrect after resize
  5. # - Handle horizontal scrollbar correctly
  6. # - Functionality: find, etc.
  7.  
  8. from Menu import DrawMenuBar
  9. from FrameWork import *
  10. import Win
  11. import Qd
  12. import TE
  13. import Scrap
  14. import os
  15. import macfs
  16.  
  17. class TEWindow(ScrolledWindow):
  18.     def open(self, path, name, data):
  19.         self.path = path
  20.         self.name = name
  21.         r = windowbounds(400, 400)
  22.         w = Win.NewWindow(r, name, 1, 0, -1, 1, 0x55555555)
  23.         self.wid = w
  24.         x0, y0, x1, y1 = self.wid.GetWindowPort().portRect
  25.         x0 = x0 + 4
  26.         y0 = y0 + 4
  27.         x1 = x1 - 20
  28.         y1 = y1 - 20
  29.         vr = dr = x0, y0, x1, y1
  30.         ##vr = 4, 0, r[2]-r[0]-15, r[3]-r[1]-15
  31.         ##dr = (0, 0, vr[2], 0)
  32.         Qd.SetPort(w)
  33.         Qd.TextFont(4)
  34.         Qd.TextSize(9)
  35.         self.ted = TE.TENew(dr, vr)
  36.         self.ted.TEAutoView(1)
  37.         self.ted.TESetText(data)
  38.         w.DrawGrowIcon()
  39.         self.scrollbars()
  40.         self.changed = 0
  41.         self.do_postopen()
  42.         self.do_activate(1, None)
  43.         
  44.     def do_idle(self):
  45.         self.ted.TEIdle()
  46.         
  47.     def getscrollbarvalues(self):
  48.         dr = self.ted.destRect
  49.         vr = self.ted.viewRect
  50.         height = self.ted.nLines * self.ted.lineHeight
  51.         vx = self.scalebarvalue(dr[0], dr[2]-dr[0], vr[0], vr[2])
  52.         vy = self.scalebarvalue(dr[1], dr[1]+height, vr[1], vr[3])
  53.         print dr, vr, height, vx, vy
  54.         return None, vy
  55.         
  56.     def scrollbar_callback(self, which, what, value):
  57.         if which == 'y':
  58.             if what == 'set':
  59.                 height = self.ted.nLines * self.ted.lineHeight
  60.                 cur = self.getscrollbarvalues()[1]
  61.                 delta = (cur-value)*height/32767
  62.             if what == '-':
  63.                 delta = self.ted.lineHeight
  64.             elif what == '--':
  65.                 delta = (self.ted.viewRect[3]-self.ted.lineHeight)
  66.                 if delta <= 0:
  67.                     delta = self.ted.lineHeight
  68.             elif what == '+':
  69.                 delta = -self.ted.lineHeight
  70.             elif what == '++':
  71.                 delta = -(self.ted.viewRect[3]-self.ted.lineHeight)
  72.                 if delta >= 0:
  73.                     delta = -self.ted.lineHeight
  74.             self.ted.TEPinScroll(0, delta)
  75.             print 'SCROLL Y', delta
  76.         else:
  77.             pass # No horizontal scrolling
  78.         
  79.     def do_activate(self, onoff, evt):
  80.         print "ACTIVATE", onoff
  81.         ScrolledWindow.do_activate(self, onoff, evt)
  82.         if onoff:
  83.             self.ted.TEActivate()
  84.             self.parent.active = self
  85.             self.parent.updatemenubar()
  86.         else:
  87.             self.ted.TEDeactivate()
  88.  
  89.     def do_update(self, wid, event):
  90.         Qd.EraseRect(wid.GetWindowPort().portRect)
  91.         self.ted.TEUpdate(wid.GetWindowPort().portRect)
  92.         self.updatescrollbars()
  93.         
  94.     def do_contentclick(self, local, modifiers, evt):
  95.         shifted = (modifiers & 0x200)
  96.         self.ted.TEClick(local, shifted)
  97.         self.updatescrollbars()
  98.         self.parent.updatemenubar()
  99.  
  100.     def do_char(self, ch, event):
  101.         self.ted.TESelView()
  102.         self.ted.TEKey(ord(ch))
  103.         self.changed = 1
  104.         self.updatescrollbars()
  105.         self.parent.updatemenubar()
  106.         
  107.     def close(self):
  108.         if self.changed:
  109.             save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?'%self.name, 1)
  110.             if save > 0:
  111.                 self.menu_save()
  112.             elif save < 0:
  113.                 return
  114.         if self.parent.active == self:
  115.             self.parent.active = None
  116.         self.parent.updatemenubar()
  117.         del self.ted
  118.         self.do_postclose()
  119.         
  120.     def menu_save(self):
  121.         if not self.path:
  122.             self.menu_save_as()
  123.             return # Will call us recursively
  124.         print 'Saving to ', self.path
  125.         dhandle = self.ted.TEGetText()
  126.         data = dhandle.data
  127.         fp = open(self.path, 'wb')  # NOTE: wb, because data has CR for end-of-line
  128.         fp.write(data)
  129.         if data[-1] <> '\r': fp.write('\r')
  130.         fp.close()
  131.         self.changed = 0
  132.         
  133.     def menu_save_as(self):
  134.         fss, ok = macfs.StandardPutFile('Save as:')
  135.         if not ok: return
  136.         self.path = fss.as_pathname()
  137.         self.name = os.path.split(self.path)[-1]
  138.         self.wid.SetWTitle(self.name)
  139.         self.menu_save()
  140.         
  141.     def menu_cut(self):
  142.         self.ted.TESelView()
  143.         self.ted.TECut()
  144.         Scrap.ZeroScrap()
  145.         TE.TEToScrap()
  146.         self.updatescrollbars()
  147.         self.parent.updatemenubar()
  148.         self.changed = 1
  149.         
  150.     def menu_copy(self):
  151.         self.ted.TECopy()
  152.         Scrap.ZeroScrap()
  153.         TE.TEToScrap()
  154.         self.updatescrollbars()
  155.         self.parent.updatemenubar()
  156.         
  157.     def menu_paste(self):
  158.         print 'SCRAP', Scrap.InfoScrap(), `Scrap.InfoScrap()[1].data`
  159.         TE.TEFromScrap()
  160.         self.ted.TESelView()
  161.         self.ted.TEPaste()
  162.         self.updatescrollbars()
  163.         self.parent.updatemenubar()
  164.         self.changed = 1
  165.         
  166.     def menu_clear(self):
  167.         self.ted.TESelView()
  168.         self.ted.TEDelete()
  169.         self.updatescrollbars()
  170.         self.parent.updatemenubar()
  171.         self.changed = 1
  172.         
  173.     def have_selection(self):
  174.         return (self.ted.selStart < self.ted.selEnd)
  175.  
  176. class Ped(Application):
  177.     def __init__(self):
  178.         Application.__init__(self)
  179.         self.num = 0
  180.         self.active = None
  181.         self.updatemenubar()
  182.         
  183.     def makeusermenus(self):
  184.         self.filemenu = m = Menu(self.menubar, "File")
  185.         self.newitem = MenuItem(m, "New window", "N", self.open)
  186.         self.openitem = MenuItem(m, "Open...", "O", self.openfile)
  187.         self.closeitem = MenuItem(m, "Close", "W", self.closewin)
  188.         m.addseparator()
  189.         self.saveitem = MenuItem(m, "Save", "S", self.save)
  190.         self.saveasitem = MenuItem(m, "Save as...", "", self.saveas)
  191.         m.addseparator()
  192.         self.quititem = MenuItem(m, "Quit", "Q", self.quit)
  193.         
  194.         self.editmenu = m = Menu(self.menubar, "Edit")
  195.         self.undoitem = MenuItem(m, "Undo", "Z", self.undo)
  196.         self.cutitem = MenuItem(m, "Cut", "X", self.cut)
  197.         self.copyitem = MenuItem(m, "Copy", "C", self.copy)
  198.         self.pasteitem = MenuItem(m, "Paste", "V", self.paste)
  199.         self.clearitem = MenuItem(m, "Clear", "", self.clear)
  200.         
  201.         # Not yet implemented:
  202.         self.undoitem.enable(0)
  203.         
  204.         # Groups of items enabled together:
  205.         self.windowgroup = [self.closeitem, self.saveitem, self.saveasitem, self.editmenu]
  206.         self.focusgroup = [self.cutitem, self.copyitem, self.clearitem]
  207.         self.windowgroup_on = -1
  208.         self.focusgroup_on = -1
  209.         self.pastegroup_on = -1
  210.         
  211.     def updatemenubar(self):
  212.         changed = 0
  213.         on = (self.active <> None)
  214.         if on <> self.windowgroup_on:
  215.             for m in self.windowgroup:
  216.                 m.enable(on)
  217.             self.windowgroup_on = on
  218.             changed = 1
  219.         if on:
  220.             # only if we have an edit menu
  221.             on = self.active.have_selection()
  222.             if on <> self.focusgroup_on:
  223.                 for m in self.focusgroup:
  224.                     m.enable(on)
  225.                 self.focusgroup_on = on
  226.                 changed = 1
  227.             on = (Scrap.InfoScrap()[0] <> 0)
  228.             if on <> self.pastegroup_on:
  229.                 self.pasteitem.enable(on)
  230.                 self.pastegroup_on = on
  231.                 changed = 1
  232.         if changed:
  233.             DrawMenuBar()
  234.  
  235.     #
  236.     # Apple menu
  237.     #
  238.     
  239.     def do_about(self, id, item, window, event):
  240.         EasyDialogs.Message("A simple single-font text editor")
  241.             
  242.     #
  243.     # File menu
  244.     #
  245.  
  246.     def open(self, *args):
  247.         self._open(0)
  248.         
  249.     def openfile(self, *args):
  250.         self._open(1)
  251.  
  252.     def _open(self, askfile):
  253.         if askfile:
  254.             fss, ok = macfs.StandardGetFile('TEXT')
  255.             if not ok:
  256.                 return
  257.             path = fss.as_pathname()
  258.             name = os.path.split(path)[-1]
  259.             try:
  260.                 fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
  261.                 data = fp.read()
  262.                 fp.close()
  263.             except IOError, arg:
  264.                 EasyDialogs.Message("IOERROR: "+`arg`)
  265.                 return
  266.         else:
  267.             path = None
  268.             name = "Untitled %d"%self.num
  269.             data = ''
  270.         w = TEWindow(self)
  271.         w.open(path, name, data)
  272.         self.num = self.num + 1
  273.         
  274.     def closewin(self, *args):
  275.         if self.active:
  276.             self.active.close()
  277.         else:
  278.             EasyDialogs.Message("No active window?")
  279.         
  280.     def save(self, *args):
  281.         if self.active:
  282.             self.active.menu_save()
  283.         else:
  284.             EasyDialogs.Message("No active window?")
  285.         
  286.     def saveas(self, *args):
  287.         if self.active:
  288.             self.active.menu_save_as()
  289.         else:
  290.             EasyDialogs.Message("No active window?")
  291.             
  292.         
  293.     def quit(self, *args):
  294.         for w in self._windows.values():
  295.             w.close()
  296.         if self._windows:
  297.             return
  298.         self._quit()
  299.         
  300.     #
  301.     # Edit menu
  302.     #
  303.     
  304.     def undo(self, *args):
  305.         pass
  306.         
  307.     def cut(self, *args):
  308.         if self.active:
  309.             self.active.menu_cut()
  310.         else:
  311.             EasyDialogs.Message("No active window?")
  312.         
  313.     def copy(self, *args):
  314.         if self.active:
  315.             self.active.menu_copy()
  316.         else:
  317.             EasyDialogs.Message("No active window?")
  318.         
  319.     def paste(self, *args):
  320.         if self.active:
  321.             self.active.menu_paste()
  322.         else:
  323.             EasyDialogs.Message("No active window?")
  324.  
  325.     def clear(self, *args):
  326.         if self.active:
  327.             self.active.menu_clear()
  328.         else:
  329.             EasyDialogs.Message("No active window?")
  330.         
  331.     #
  332.     # Other stuff
  333.     #    
  334.  
  335.     def idle(self, *args):
  336.         if self.active:
  337.             self.active.do_idle()
  338.  
  339. def main():
  340.     App = Ped()
  341.     App.mainloop()
  342.     
  343. if __name__ == '__main__':
  344.     main()
  345.     
  346.